Skip to content

chore(ci-scope): add scope:* tags + implicitDependencies (PR 1/3)#503

Merged
blove merged 5 commits into
mainfrom
claude/ci-scope-hybrid
May 21, 2026
Merged

chore(ci-scope): add scope:* tags + implicitDependencies (PR 1/3)#503
blove merged 5 commits into
mainfrom
claude/ci-scope-hybrid

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 21, 2026

Summary

  • Adds scope:* tags to every CI-participating project.json (~87 files), making scope membership a data declaration rather than a hand-maintained code rule.
  • Adds implicitDependencies on apps/cockpit and apps/website for the non-project files (vercel..json, scripts/.ts, capability-registry.ts) that currently live in applyFallbackPathScope.
  • No behavior change: scripts/ci-scope.mjs is untouched — it still drives gating via its existing rules. The new metadata is inert until PR 2.

See spec: docs/superpowers/specs/2026-05-21-ci-scope-thin-shim-design.md
See plan: docs/superpowers/plans/2026-05-21-ci-scope-thin-shim-plan.md

Known concern

//scripts/deploy-smoke.ts is included in apps/cockpit's implicitDependencies per the spec, but this file does not exist at the repo root. It only exists at apps/cockpit/scripts/deploy-smoke.ts (already separately listed). The entry is stale in the spec. Leaving it as-is per the plan's instruction to report rather than silently remove — please confirm whether to drop the duplicate root-level entry.

Test plan

  • CI passes (nx affected commands unaffected — metadata is inert)
  • nx graph loads cleanly (node_modules needed; CI will validate)
  • Spot-check: libs/chat/project.json has all 10 broadcast scope tags
  • Spot-check: cockpit/chat/messages/angular/project.json has scope:cockpit-e2e + scope:cockpit-examples
  • Spot-check: apps/cockpit/project.json has 12-entry implicitDependencies list

🤖 Generated with Claude Code

blove and others added 3 commits May 20, 2026 20:51
Task #16 (final audit item). Shrinks scripts/ci-scope.mjs from 340 LOC
to ~50 LOC by replacing hand-maintained applyProjectScope and
applyFallbackPathScope rules with data:

1. Per-project `scope:*` tags declare which CI gates a project triggers.
   The shim reads tags off projects nx considers affected.
2. Non-project fallback paths (vercel.*.json, deploy scripts, registry,
   etc.) move into project.json implicitDependencies. Nx considers the
   target project affected via the implicit dep edge.

Migration sequenced as 3 PRs: (1) metadata add (no behavior change),
(2) shim rewrite + test migration, (3) cleanup + drift-guard assertion.

Preserves all current CI gate semantics + true-skip job behavior;
adds 2-5s nx-affected startup vs current sub-second classifier (already
analyzed in the brainstorm — acceptable trade-off for the project-graph
correctness + dependency cascading wins).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8-task plan sequenced across 3 PRs:
- PR 1 (Task 1): scripted addition of scope:* tags + implicitDependencies
  on ~50 project.json files. No behavior change.
- PR 2 (Tasks 2-6): rewrite scripts/ci-scope.mjs as ~120-LOC thin shim
  over `nx show projects --affected`. Migrate scripts/ci-scope.spec.mjs.
  Smoke test against recent main range.
- PR 3 (Tasks 7-8): drift-guard assertion in cockpit-e2e-wiring.spec.ts
  that every cap project has expected scope:* tags.

Each PR ships independently. PR 2's own CI run is the integration test;
do not admin-merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… change)

PR 1 of 3 for the ci-scope thin-shim migration. Adds metadata only:

1. scope:* tags on every CI-participating project, replacing the
   hand-maintained applyProjectScope rules in scripts/ci-scope.mjs
   with data declarations next to each project.

2. implicitDependencies on apps/cockpit and apps/website pointing at
   the non-project files (vercel.*.json, scripts/*.ts, capability-
   registry.ts) that currently live in applyFallbackPathScope.

ci-scope.mjs unchanged in this PR — still drives gating via the old
rules. The new metadata is inert. PR 2 will rewrite the shim to read
from this metadata; PR 3 will add a drift-guard assertion.

See docs/superpowers/specs/2026-05-21-ci-scope-thin-shim-design.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment May 21, 2026 4:42am

Request Review

The original spec listed this path as a fallback file (mirroring the
OLD ci-scope.mjs's defensive `if (changedFile === 'apps/cockpit/scripts/
deploy-smoke.ts' || changedFile === 'scripts/deploy-smoke.ts')` check),
but only the apps/cockpit/scripts/deploy-smoke.ts path exists on this
repo today. The root-level path is dead — the OLD rule was overly
defensive for a file that was never created at that path.

The legitimate //apps/cockpit/scripts/deploy-smoke.ts entry remains.

Caught by the existence check in Task 1 Step 4 of the migration plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR 1 added `implicitDependencies: ["//vercel.json", ...]` to apps/cockpit
and apps/website. On Nx 22.5.1, this caused all cockpit-* CI gates to
fail (29 failures: build/test, build-all-examples, 18 e2e matrix
expansions, etc.). The `//path` syntax for file-level implicit deps
either isn't recognized by Nx 22 or requires different escaping.

Revert just the implicitDependencies. Keep the scope:* tags addition —
those are inert metadata and use the existing tags pattern.

PR 2's shim rewrite will need to either:
(a) Restore implicitDependencies with the correct syntax once verified,
    or
(b) Keep applyFallbackPathScope's file-by-file rules in ci-scope.mjs
    (shim ends up ~80 LOC instead of ~50).

Either way, PR 1's scope-tags addition is still useful as data for the
shim to read.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@blove blove merged commit 2f80bfd into main May 21, 2026
37 of 38 checks passed
blove added a commit that referenced this pull request May 21, 2026
…ncies (#505)

* docs(ci-scope): revise spec — namedInputs over implicitDependencies

PR #503 surfaced that Nx 22.5.1 rejects file-path syntax in
implicitDependencies entries (validates strictly as project names;
errored: "implicitDependencies point to non-existent project(s)"
on //path). The Nx-native mechanism for file-level affecting-deps is
per-project namedInputs referenced by target inputs.

Spec updates:
- Header revision note documenting the discovery.
- Replace "implicitDependencies — fallback paths become first-class"
  section with "namedInputs — fallback paths become first-class".
- Concrete project.json example uses namedInputs.deploymentConfig
  with {workspaceRoot}/... paths, bound to target inputs.
- Migration sequencing updated: PR 1 retroactively documented as
  "tags only (shipped)"; PR 2 includes the namedInputs migration.
- Risk surface revised: namedInputs target-binding fragility (must
  reference in target inputs to take effect).
- Acceptance criteria updated.

The shim still targets ~50 LOC; the migration goal is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(ci-scope): revise plan to match namedInputs spec

PR 1's Task 1 collapsed to a SHIPPED stub with archived tag-categorization
rules in a <details> block. Adds Task 2.5 to PR 2: add namedInputs.
deploymentConfig to apps/cockpit and apps/website project.json,
reference in build target inputs, smoke-test that nx affected picks
up vercel.cockpit.json changes correctly.

Keeps Tasks 3-8 unchanged (shim rewrite, test migration, smoke, commit,
drift guard) — those don't depend on the implicitDependencies vs
namedInputs distinction beyond the smoke-test expectations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
blove added a commit that referenced this pull request May 21, 2026
* refactor(ci-scope): replace classifier with thin shim over nx affected

PR 2 of 3 for the ci-scope thin-shim migration. PR 1 (#503) added
scope:* tags to 87 project.json files; this PR makes ci-scope.mjs
actually read them via `nx show projects --affected`.

apps/cockpit + apps/website: namedInputs.deploymentConfig
- Per-project namedInputs declare which non-project files affect each
  project: vercel.*.json, scripts/deploy-smoke.ts, capability-registry.ts,
  etc. on apps/cockpit; vercel.json on apps/website.
- Referenced from each project's build target inputs so nx considers
  them when computing affected.
- Replaces ~50 LOC of applyFallbackPathScope rules with Nx-native data.
- Smoke-verified: `nx show projects --affected` correctly marks
  `cockpit` as affected when vercel.cockpit.json changes.

scripts/ci-scope.mjs: 340 LOC → 120 LOC.
- applyProjectScope (~80 LOC of project-walking rules) → replaced by
  ~10-LOC tag-driven classifyFromAffected reading from
  `nx show projects --affected --json`.
- applyFallbackPathScope (~50 LOC of file-path rules) → replaced by
  the namedInputs above.
- discoverProjects walk (~30 LOC of filesystem traversal) → gone.
- GLOBAL_CI_FILES short-circuit (.github/workflows/ci.yml etc.) kept.
- Backward-compatible CLI: --base/--head/--output/--event=push.

scripts/ci-scope.spec.mjs: full rewrite.
- Tests inject synthetic affectedProjects arrays with tag arrays directly
  (no more synthetic workspace+ownsPath fixtures).
- 13 tests across 5 describe blocks: short-circuit, publishable lib
  broadcast, cockpit cap angular/python, fallback paths via namedInputs,
  tag isolation (non-scope tags + unknown scope keys ignored).

Backward-compatible workflow gating: same scope booleans emit for the
same file changes. Jobs still truly skip (no per-job fast-pass cost).

This PR's own CI run is the integration test. DO NOT admin-merge — if
the new shim misclassifies, its own gates fire wrong. Verify scope
output in the CI scope job's logs before merging.

See docs/superpowers/specs/2026-05-21-ci-scope-thin-shim-design.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci-scope): use node:test (not vitest) in ci-scope.spec.mjs

CI runs `node --test scripts/ci-scope.spec.mjs` directly (no vitest
installed at the ci-scope job's pre-npm-ci stage). My PR 2 rewrite
imported `describe, it, expect` from 'vitest' and used Chai-style
matchers; CI errored with ERR_MODULE_NOT_FOUND on 'vitest'.

Rewrite spec to use Node's built-in test runner:
- import { describe, it } from 'node:test'
- import assert from 'node:assert/strict'
- expect(x).toBe(y) → assert.equal(x, y)
- expect(x).toEqual(y) → assert.deepEqual(x, y)

All 13 tests pass via `node --test`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci(ci-scope): add setup-node + npm ci so the new shim can call nx affected

PR 2's ci-scope.mjs rewrite delegates project ownership to `nx show
projects --affected --json`. The CI scope job previously had no node
setup or npm install (just `actions/checkout` + `node --test`), so
the new shim errored with "Could not find Nx modules" at runtime.

Add setup-node@v6 (node 22, cache: npm) + `npm ci` before the
classifier test and the scope-detection step. Tax: ~15-30s warm cache,
~60s cold cache, on every CI run. This is the one-time-per-PR cost of
using nx's project graph as the source of truth instead of a hand-
maintained classifier walk.

Comment block in the ci.yml explains the rationale so reviewers
understand why setup got more elaborate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
blove added a commit that referenced this pull request May 21, 2026
#509)

PR 3 of 3 for the ci-scope thin-shim migration. PR 1 (#503) added
scope:* tags to every CI-participating project; PR 2 (#507) rewrote
ci-scope.mjs to read them via `nx show projects --affected --json`.
This drift-guard asserts every cockpit cap project (angular + python
under cockpit/<product>/<topic>/) declares the expected tags:

- scope:cockpit-e2e + scope:cockpit-examples on every cap project.
- scope:cockpit-smoke on python caps that have a smoke target.

Closes the silent-failure mode: future contributors adding a new cap
can't forget the tags — the test names which project + which tag is
missing.

Excludes cockpit/ag-ui/* (no python sibling; different tag rules).

See spec: docs/superpowers/specs/2026-05-21-ci-scope-thin-shim-design.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant